package com.punai.monthanalysis.bo;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.multi.ListValueMap;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.punai.common.utils.NumberUtil;
import com.punai.common.utils.StringUtil;
import com.punai.common.utils.bean.BeanUtils;
import com.punai.externalccb.bo.YdCbfeeiteminfoStandardBo;
import com.punai.externalccb.domain.EcoMeasureitem;
import com.punai.externalccb.domain.YdBqitemMate;
import com.punai.monthanalysis.constants.YdcbfxConstants;
import com.punai.monthanalysis.domain.ProYdcbfxGcjdkhcldbfxb;
import com.punai.monthanalysis.domain.ProYdcbfxGcjdkhrgfdbfxb;
import com.punai.monthanalysis.domain.ProYdcbfxRgfdbfxb;
import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

public class ProYdcbfxRgfdbfxbBo extends ProYdcbfxRgfdbfxb {

    private Integer rowspan = 1;
    private Integer colspan = 1;
    private List<ProYdcbfxRgfdbfxbBo> children = new ArrayList<>();

    public Integer getRowspan() {
        return rowspan;
    }

    public void setRowspan(Integer rowspan) {
        this.rowspan = rowspan;
    }

    public Integer getColspan() {
        return colspan;
    }

    public void setColspan(Integer colspan) {
        this.colspan = colspan;
    }

    public List<ProYdcbfxRgfdbfxbBo> getChildren() {
        return children;
    }

    public void setChildren(List<ProYdcbfxRgfdbfxbBo> children) {
        this.children = children;
    }

    public void clearColRow() {
        this.setRowspan(0);
        this.setColspan(0);
    }

    public static List<ProYdcbfxRgfdbfxbBo> convertStandard(List<YdCbfeeiteminfoStandardBo> list, Map<Integer, List<YdBqitemMate>> reltypeMap){
        List<ProYdcbfxRgfdbfxbBo> result = new ArrayList<>();
        if (CollUtil.isEmpty(list)) {
            return null;
        }
        for (YdCbfeeiteminfoStandardBo standard : list) {
            ProYdcbfxRgfdbfxbBo bo = new ProYdcbfxRgfdbfxbBo();
            bo.setId(standard.getId());
            bo.setProId(standard.getProId());
            bo.setQc(standard.getYdDate());//期次Id
            bo.setCategory(standard.getCategoryName()==null?"":standard.getCategoryName());//分类
            bo.setItemName(standard.getName());
            bo.setUnit(standard.getUnit());

            bo.setYsQuantity(standard.getMonthAmount());
            bo.setYsAvgPrice(standard.getMonthPrice());
            bo.setYsPrice(standard.getMonthCzTotal());

            bo.setSjQuantity(standard.getActualCostAmout());
            bo.setSjAvgPrice(standard.getActualCostNoTaxPrice());
            bo.setSjPrice(standard.getActualCostNoTaxTotal());

            BigDecimal ysAmount = standard.getMonthAmount();
            BigDecimal ysTotal = standard.getMonthCzTotal();
            BigDecimal jcQuantity = standard.getDifferenceOfCzsjAmount();
            BigDecimal quantityJcl = NumberUtil.divideNew(jcQuantity, 2, ysAmount);
            BigDecimal price = standard.getKlDifferenceOfCzsjTotal();
            BigDecimal priceJcl = NumberUtil.divideNew(price, 2, ysTotal);
            bo.setJcQuantity(jcQuantity);
            bo.setQuantityJcl(quantityJcl);
            bo.setPrice(price);
            bo.setPriceJcl(priceJcl);
            result.add(bo);
        }
        return convert(result,reltypeMap);
    }

    public static List<ProYdcbfxRgfdbfxbBo> convert(List<ProYdcbfxRgfdbfxbBo>  allList,Map<Integer, List<YdBqitemMate>> reltypeMap) {
        List<ProYdcbfxRgfdbfxbBo> result = new ArrayList<>();
        if (CollUtil.isEmpty(allList)) {
            return result;
        }
        if (CollUtil.isNotEmpty(reltypeMap)){
            for (Map.Entry<Integer, List<YdBqitemMate>> entry : reltypeMap.entrySet()) {
                Integer key = entry.getKey();
                String desc = YdcbfxConstants.TABS_RGFDBFXB_DATATYPE.getDescByDataType(key.toString());
                List<YdBqitemMate> value = entry.getValue();
                List<ProYdcbfxRgfdbfxbBo> collect = allList.stream().filter(
                        a ->
                                value.stream().map(YdBqitemMate::getCbfeeiteminfoid)
                                        .anyMatch(
                                                infoId -> Objects.equals(a.getId(), infoId)
                                        )
                ).collect(Collectors.toList());
                List<ProYdcbfxRgfdbfxbBo> convert = convertProBo(collect);
                result.addAll(convert);
                BigDecimal ysAmount = convert.stream().map(ProYdcbfxRgfdbfxb::getYsQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO,BigDecimal::add);
                BigDecimal ysAvgPrice = convert.stream().map(ProYdcbfxRgfdbfxb::getYsAvgPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO,BigDecimal::add);
                BigDecimal ysPrice = convert.stream().map(ProYdcbfxRgfdbfxb::getYsPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO,BigDecimal::add);
                BigDecimal sjAmount = convert.stream().map(ProYdcbfxRgfdbfxb::getSjQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO,BigDecimal::add);
                BigDecimal sjAvgPrice = convert.stream().map(ProYdcbfxRgfdbfxb::getSjAvgPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO,BigDecimal::add);
                BigDecimal sjPrice = convert.stream().map(ProYdcbfxRgfdbfxb::getSjPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO,BigDecimal::add);
                BigDecimal jcQuantity = NumberUtil.subtractNew(ysAmount, sjAmount);
                BigDecimal jcQuantityJcl = NumberUtil.divideNew(jcQuantity, 2, ysAmount);
                BigDecimal price = NumberUtil.subtractNew(ysPrice, sjPrice);
                BigDecimal priceJcl = NumberUtil.divideNew(price, 2, ysPrice);
                ProYdcbfxRgfdbfxbBo bo = new ProYdcbfxRgfdbfxbBo();
                bo.setCategory(desc);
                bo.setYsQuantity(ysAmount);
                bo.setYsAvgPrice(ysAvgPrice);
                bo.setYsPrice(ysPrice);
                bo.setSjQuantity(sjAmount);
                bo.setSjAvgPrice(sjAvgPrice);
                bo.setSjPrice(sjPrice);
                bo.setJcQuantity(jcQuantity);
                bo.setQuantityJcl(jcQuantityJcl);
                bo.setPrice(price);
                bo.setPriceJcl(priceJcl);
                bo.setColspan(2);
                result.add(bo);
            }
        }
        List<ProYdcbfxRgfdbfxbBo> HJList = result.stream().filter(v -> v.getColspan() == 2).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(HJList)){
            BigDecimal ysPrice = HJList.stream().map(ProYdcbfxRgfdbfxb::getYsPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal sjPrice = HJList.stream().map(ProYdcbfxRgfdbfxb::getSjPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal price = NumberUtil.subtractNew(ysPrice, sjPrice);
            ProYdcbfxRgfdbfxbBo boHJ = new ProYdcbfxRgfdbfxbBo();
            boHJ.setCategory("合计");
            boHJ.setYsPrice(ysPrice);
            boHJ.setSjPrice(sjPrice);
            boHJ.setPrice(price);
            boHJ.setPriceJcl(NumberUtil.divideNew(price, 2, ysPrice));
            boHJ.setColspan(2);
            result.add(boHJ);
        }
        return result;
    }

    public static List<ProYdcbfxRgfdbfxbBo> convertProBo(List<ProYdcbfxRgfdbfxbBo> list) {
        List<ProYdcbfxRgfdbfxbBo> result = new ArrayList<>();
        if (CollUtil.isEmpty(list)) {
            return result;
        }
        Map<String, List<ProYdcbfxRgfdbfxbBo>> listMap = list.stream()
                .peek(v -> {
                    if (StringUtil.isNullOrEmpty(v.getCategory())){
                        v.setCategory("");
                    }
                }).collect(Collectors.groupingBy(ProYdcbfxRgfdbfxbBo::getCategory, Collectors.toList()));
        for (Map.Entry<String, List<ProYdcbfxRgfdbfxbBo>> listEntry : listMap.entrySet()) {
            List<ProYdcbfxRgfdbfxbBo> entryValues = listEntry.getValue();
            for (int i = 0; i < entryValues.size(); i++) {
                ProYdcbfxRgfdbfxbBo bo = entryValues.get(i);
                ProYdcbfxRgfdbfxbBo copy = new ProYdcbfxRgfdbfxbBo();
                BeanUtils.copyProperties(bo,copy);
                if (i == 0){
                    copy.setRowspan(entryValues.size());
                }else {
                    copy.setCategory(null);
                    copy.clearColRow();
                }
                result.add(copy);
            }
        }
        return result;
    }

    public static List<ProYdcbfxRgfdbfxbBo> convert(List<ProYdcbfxRgfdbfxb> inList) {
        List<ProYdcbfxRgfdbfxbBo> result = new ArrayList<>();
        if (CollUtil.isEmpty(inList)) {
            return result;
        }
        Map<String, List<ProYdcbfxRgfdbfxb>> dataTypeMap = inList.stream().collect(Collectors.groupingBy(ProYdcbfxRgfdbfxb::getDatatype));

        Set<String> keySet = dataTypeMap.keySet();
        ListValueMap<String,ProYdcbfxRgfdbfxb> levelMap = new ListValueMap<>();


        ProYdcbfxRgfdbfxbBo allHjBo = new ProYdcbfxRgfdbfxbBo();
        List<ProYdcbfxRgfdbfxbBo> hjBoList = new ArrayList<>();
        for (String dataType : keySet) {
            List<ProYdcbfxRgfdbfxb> proYdcbfxRgfdbfxbs = dataTypeMap.get(dataType);


            for (ProYdcbfxRgfdbfxb proYdcbfxRgfdbfxb : proYdcbfxRgfdbfxbs) {
                levelMap.putValue(StrUtil.blankToDefault(proYdcbfxRgfdbfxb.getPid(),"0"),proYdcbfxRgfdbfxb);
            }
            List<ProYdcbfxRgfdbfxb> roots = levelMap.get("0");
            // 拆解2层
            roots.sort(Comparator.comparing(ProYdcbfxRgfdbfxb::getXh));
            ProYdcbfxRgfdbfxbBo hjBo = new ProYdcbfxRgfdbfxbBo();
            for (ProYdcbfxRgfdbfxb root : roots) {
                String id = root.getId();
                ProYdcbfxRgfdbfxbBo convert = ProYdcbfxRgfdbfxbBo.convert(root);
                List<ProYdcbfxRgfdbfxb> childrenList = levelMap.get(id);
                if (CollUtil.isNotEmpty(childrenList)) {
                    convert.setRowspan(childrenList.size() + 1);
                    result.add(convert);
                    childrenList.sort(Comparator.comparing(ProYdcbfxRgfdbfxb::getXh));

                    for (ProYdcbfxRgfdbfxb child : childrenList) {
                        ProYdcbfxRgfdbfxbBo childrenBo = convert(child);
                        childrenBo.clearColRow();
                        result.add(childrenBo);
                    }
                }
            }
            String desc = YdcbfxConstants.TABS_RGFDBFXB_DATATYPE.getDescByDataType(dataType);

            BigDecimal ysPrice = roots.stream().map(ProYdcbfxRgfdbfxb::getYsPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal sjPrice = roots.stream().map(ProYdcbfxRgfdbfxb::getSjPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal price = roots.stream().map(ProYdcbfxRgfdbfxb::getPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            hjBo.setYsPrice(ysPrice);
            hjBo.setSjPrice(sjPrice);
            hjBo.setPrice(price);
            hjBo.setPriceJcl(NumberUtil.divide(price,3,ysPrice));

            hjBo.setCategory(desc);
            hjBo.setColspan(2);
            result.add(hjBo);
            hjBoList.add(hjBo);
            levelMap.clear();
        }

        BigDecimal ysPrice = hjBoList.stream().map(ProYdcbfxRgfdbfxb::getYsPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal sjPrice = hjBoList.stream().map(ProYdcbfxRgfdbfxb::getSjPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal price = hjBoList.stream().map(ProYdcbfxRgfdbfxb::getPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

        allHjBo.setCategory("合计");
        allHjBo.setColspan(2);
        allHjBo.setYsPrice(ysPrice);
        allHjBo.setSjPrice(sjPrice);
        allHjBo.setPrice(price);
        allHjBo.setPriceJcl(NumberUtil.divide(price,3,ysPrice));
        result.add(allHjBo);
        return result;
    }

    public static ProYdcbfxRgfdbfxbBo convert(ProYdcbfxRgfdbfxb in) {
        ProYdcbfxRgfdbfxbBo out = new ProYdcbfxRgfdbfxbBo();
        BeanUtils.copyBeanProp(out,in);
        return out;
    }


}
